package org.oimwrapper.connectors.genericldap;

import java.util.*;

/**
 * Reconciles users along with pulling the full DN values of all the groups that user is a member of into a multivalued 
 * attribute. <p>
 *
 * This task expects the following parameters, in addition to the standard parameters in the {@link OIMLdapUserReconciliation} class.
 * <ul>
 * <li><code>MemberOfAttribute</code> The name of the attribute in which the group membership will be stored.</li>
 * <li><code>GroupSearchScope</code> This can be either <code>subtree</code> for a full, multi-level search, <code>single</code>
 * to only search the current level, or <code>base</code> to only search the base object.</li>
 * <li><code>GroupSearchBase</code> The DN to use as the search base for groups.  If <code>[NONE]</code> is specified, then 
 * the root DN specified on the IT resource will be used.</li>
 * <li><code>GroupsAsDN</code> Settings this to <code>true</code> indicates that groups should be pulled in as DN's, setting
 * this to <code>false</code> will pull in the groups as only the container name values.</li>
 * </ul>
 */
public class OIMLdapUserMemberReconciliation extends OIMLdapUserReconciliation {

	/**
	 * This method is called once to retrieve a List of records on the target system.   The objects in this 
	 * list are consumed by the <code>getSingleValuedData()</code> and <code>getMultiValuedData()</code>
	 * methods, and not directly used by any other methods.
	 * 
	 * @return A List of records on the target system.
	 * @exception Exception
	 */
	public List getRecords() throws Exception {
		logger.debug("Entering ::getRecords()");
		List results = super.getRecords();
		String memberOfAttribute = getDefaultAttribute("MemberOfAttribute", "memberOf");
		multiAttributes.put(memberOfAttribute, memberOfAttribute);
        	for (Iterator iterator = results.iterator(); iterator.hasNext(); ) {
			OIMLdapObject account = (OIMLdapObject) iterator.next();
			account.setAttributeToNull(memberOfAttribute);
			boolean useDnForMember = ldap.lookupParameter("useDnForMember").equalsIgnoreCase("true");
			String groupMemberAttribute = ldap.lookupParameter("groupMemberAttribute");
			String groupIDAttribute = ldap.lookupParameter("groupIDAttribute");
			String objectClassAttribute = ldap.lookupParameter("objectClassAttribute");
			String defaultGroupObjectClass = ldap.lookupParameter("defaultGroupObjectClass");
			String accountKey = useDnForMember ? account.getIndexingID(dnAttribute) : account.getAttribute(loginAttribute)[0];
			String searchBase = getDefaultAttribute("GroupSearchBase", (String) itResData.get("Root DN"));
            		String filter = "(&(" + objectClassAttribute + "=" + defaultGroupObjectClass + ")(" + groupMemberAttribute + "=" + accountKey + "))";
			logger.debug("filter = " + filter);
			String[] attributes = new String[] { dnAttribute };
			String scope = getDefaultAttribute("GroupSearchScope", "subtree");
			OIMLdapResultSet groups = ldap.search(searchBase, filter, attributes, false, scope);
			String[] keys = groups.getKeys();
			for (int i = 0; i < keys.length; i++) {
				if (getBooleanAttribute("GroupsAsDN", true)) {
					account.appendToAttribute(memberOfAttribute, keys[i]);
				} else {
					String name = groups.getObject(keys[i]).getAttribute(groupIDAttribute)[0];
					account.appendToAttribute(memberOfAttribute, name);
				}
			}
		}
		logger.debug("Exiting ::getRecords()");
		return results;
	}
}